Functions for Debugging p4 Programs

debugging

P4 has a set of routines to aid in producing a printed trace of events, both user-defined and pre-defined in the p4 system.

p4_dprintf
\begin{example}
VOID p4_dprintf(fmt, va_alist)
char *fmt;
va_dcl
\end{example}
acts just like the standard printf except that the print line is preceded by a value that identifies the process. This value is typically the string pn_u where n represents the p4-assigned id and u represents the unix-id of the process on its host. However, there are other forms of this value. For example, the big master is represented as bm_u. Also, if a process prints before it has a p4-assigned id, then its value will be something like bm_slave_n_u or rm_slave_n_u. Typically, it is not possible for a user program to print anything before being assigned an id by p4, but the p4 system itself may use this procedure to print messages from a particular process if it encounters problems getting the process initialized.

p4_dprintfl
\begin{example}
VOID p4_dprintfl(level, fmt, va_alist)
int level;
char *fmt;
va_dcl
\end{example}
is like p4_dprintf except that the first argument is an integer indicating the debugging level that must be in effect before this message will print. A level of 0 will cause the message to always print. If you run a program with the debug level set to 5 (via command-line arguments), then all dprintfl's with level less than or equal to that debug level will print. Command-Line Arguments for how to set the debug level at run time.

The debug level can be examined and changed by the user during execution:

p4_get_dbg_level
\begin{example}
int p4_get_dbg_level()
\end{example}
returns the current debug level for this process and its cluster.

p4_set_dbg_level
\begin{example}
VOID p4_set_dbg_level(level)
int level;
\end{example}
sets the current debug level for this process and its cluster. P4 itself is liberally instrumented with p4_dprintfl's of level 10 and above, leaving levels 0-9 for the user. The greater the debug level of the built-in messages, the greater understanding of p4 needed by the user to make sense of them. However, levels as high as 30 may well be useful to the user trying to debug a p4 program. Roughly speaking, the following debug levels produce messages about the indicated events.


\begin{example}
level 10: created process
sent message
received message
\par
l...
...ialization
\par
level 90: detailed tracing of flow thru procedures
\end{example}

For optimum performance, the test of the debug level required by these messages can be removed at compile time by not commenting out the #define P4_DPRINTFL line in the OPTIONS file. (Structure of the Distribution Directory).

The following function is provided to deal with abnormal termination. It can be called by any process.

p4_error
\begin{example}
VOID p4_error(string, value)
char *string;
int value;
\end{example}
prints string as an error message and then forcefully terminates all co-operating processes and cleans up all shared resources.

p4_soft_errors
\begin{example}
VOID p4_soft_errors(onoff)
int onoff;
\end{example}
enables/disables soft errors, returning the previous setting. The default is ``disabled'', which means that certain p4 functions will call p4_error instead of returning -1.

interrupts p4_error gets control on certain kinds of interrupts. It is automatically called for SIGSEGV, SIGBUS, and SIGFPE interrupts, to catch user programming errors and clean up, after which it returns interrupt handling to default mode and returns, so that the user may obtain a dump. It also handles SIGINT interrupts, in which case it cleans up and exits. Finally, it may be called directly by the user, in which case it cleans up (other p4 processes and IPC's) and exits.

runaway processes Although p4_error is supposed to get rid of all running p4 processes, it can happen that an error is bad enough that p4 processes are left running. A primitive aid in finding and killing these processes is the shell script kj, which takes a string as an argument and then kills processes containing that string as part of their program names. Currently it only kills processes on the machine where it is run, but it can be run via rsh on remote machines. There are other useful scripts (e.g. killipc and killp4) in the p4/bin directory to do such things as clean up SYSV IPC items that may be left when a program abnormally terminates. P4 will generally cleanup these items if the abnormal termination is a type that p4 traps, otherwise the user must do the cleanup. This is an unfortunate side-effect of the way that SYSV handles things, it really should be the OS's function to take care of this.

On many machines it is possible to attach a debugger like dbx to a running process. This is one way to find out where a hanging process is stuck.

Miscellaneous Functions,Fortran Interface,Functions for Debugging p4 Programs,Top